<template>
  <div class="xtx-city" ref="target">
    <div class="select" @click="toggle">
      <span class="placeholder" v-if="!locationData">请选择配送地址</span>
      <span class="value" @click="toggle" else>{{ locationData }}</span>
      <i class="iconfont icon-angle-down"></i>
    </div>
    <div class="option" v-if="visible">
      <template v-if="cityData">
        <span
          class="ellipsis"
          @click="updateSelectedCityData(item)"
          v-for="item in list"
          :key="item.code"
          >{{ item.name }}</span
        >
      </template>
      <template v-else>
        <div class="loading"></div>
      </template>
    </div>
  </div>
</template>
<script>
import { computed, reactive, ref } from "vue";
import { onClickOutside } from "@vueuse/core";
import axios from "axios";

export default {
  name: "XtxCity",
  setup(props, { emit }) {
    // 控制弹窗显示隐藏
    const visible = ref(false);
    // 用于存储城市数据
    const cityData = ref(null);
    // 用户选择的城市数据
    const selectedCityData = reactive({
      // 记录城市编码  code用于发送服务器端
      provinceCode: "",
      cityCode: "",
      countyCode: "",
      // 记录名字 name用于模板展示
      provinceName: "",
      cityName: "",
      countyName: "",
    });
    // 用于展示用于选择的省市区数据
    const locationData = ref();

    // 记录用户选择的是什么
    const updateSelectedCityData = (item) => {
      console.log(item);
      // item.level 如果等于 0是省 1是市 2是区
      if (item.level === 0) {
        selectedCityData.provinceCode = item.code;
        selectedCityData.provinceName = item.name;
      } else if (item.level === 1) {
        selectedCityData.cityCode = item.code;
        selectedCityData.cityName = item.name;
      } else if (item.level === 2) {
        selectedCityData.countyCode = item.code;
        selectedCityData.countyName = item.name;
      }
    };
    // 替换页面中的省市区数据
    const list = computed(() => {
      // 初始为省数据
      let cityList = cityData.value;
      // 判断是否选择了省级数据
      if (selectedCityData.provinceCode) {
        cityList = cityList.find(
          (item) => item.code === selectedCityData.provinceCode
        ).areaList;
      }
      // 判断是否选择了市级数据
      if (selectedCityData.cityCode) {
        cityList = cityList.find(
          (item) => item.code === selectedCityData.cityCode
        ).areaList;
      }
      // 判断是否选择了区级数据 关闭弹窗
      if (selectedCityData.countyCode) {
        // 收集code数据
        const { provinceCode, cityCode, countyCode } = selectedCityData;
        // 发送给父组件
        emit("onCityChanged", { provinceCode, cityCode, countyCode });
        // 重置省级列表
        cityList = cityData.value;
        hide();
      }

      return cityList;
    });

    // 获取整个弹框元素
    const target = ref();
    window.cityData = null;

    // 让弹框显示
    const show = () => {
      visible.value = true;
      getCityData().then((data) => {
        cityData.value = data;
      });
    };

    // 让弹框隐藏
    const hide = () => {
      visible.value = false;
      // 判断用户是否选择了完整的省市区级数据
      if (selectedCityData.countyName) {
        // 清空前 储存name
        locationData.value = `${selectedCityData.provinceName}${selectedCityData.cityName}${selectedCityData.countyName}`;
      }
      // 隐藏后清空省市区Code数据
      for (let attr in selectedCityData) {
        selectedCityData[attr] = "";
      }
    };
    // 让弹框切换显示隐藏
    const toggle = () => {
      visible.value ? hide() : show();
    };
    // 点击元素外 触发回调函数
    onClickOutside(target, () => {
      hide();
    });
    return {
      visible,
      show,
      hide,
      toggle,
      target,
      cityData,
      selectedCityData,
      updateSelectedCityData,
      list,
      locationData,
    };
  },
};
const getCityData = async () => {
  // 判断window中 是否有数据
  if (window.cityData) return window.cityData;

  // 获取数据
  let data = await axios
    .get(
      "https://yjy-oss-files.oss-cn-zhangjiakou.aliyuncs.com/tuxian/area.json"
    )
    .then((res) => {
      // 把数据缓存到window中
      return res.data;
    });
  // 缓存城市数据
  return (window.cityData = data);
};
</script>
<style scoped lang="less">
.xtx-city {
  display: inline-block;
  position: relative;
  z-index: 400;
  .select {
    border: 1px solid #e4e4e4;
    height: 30px;
    padding: 0 5px;
    line-height: 28px;
    cursor: pointer;
    &.active {
      background: #fff;
    }
    .placeholder {
      color: #999;
    }
    .value {
      color: #666;
      font-size: 12px;
    }
    i {
      font-size: 12px;
      margin-left: 5px;
    }
  }
  .option {
    width: 542px;
    border: 1px solid #e4e4e4;
    position: absolute;
    left: 0;
    top: 29px;
    background: #fff;
    min-height: 30px;
    line-height: 30px;
    display: flex;
    flex-wrap: wrap;
    padding: 10px;
    .loading {
      height: 290px;
      width: 100%;
      background: url(../../assets/images/loading.gif) no-repeat center;
    }
    > span {
      width: 130px;
      text-align: center;
      cursor: pointer;
      border-radius: 4px;
      padding: 0 3px;
      &:hover {
        background: #f5f5f5;
      }
    }
  }
}
</style>
